package com.aiwiown.snackmq.storage.util;

import lombok.extern.slf4j.Slf4j;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 资源管理器 - 确保所有资源都被正确释放
 * 避免文件句柄泄漏和内存泄漏
 */
@Slf4j
public final class ResourceManager {

    private ResourceManager() {}

    /**
     * 安全关闭资源
     * 
     * @param closeable 可关闭的资源
     * @param resourceName 资源名称（用于日志）
     */
    public static void safeClose(Closeable closeable, String resourceName) {
        if (closeable == null) {
            return;
        }
        
        try {
            closeable.close();
            log.debug("Successfully closed resource: {}", resourceName);
        } catch (IOException e) {
            log.warn("Failed to close resource: {}", resourceName, e);
        } catch (Exception e) {
            log.error("Unexpected error closing resource: {}", resourceName, e);
        }
    }

    /**
     * 安全关闭文件通道
     * 
     * @param channel 文件通道
     * @param resourceName 资源名称
     */
    public static void safeCloseChannel(FileChannel channel, String resourceName) {
        if (channel == null) {
            return;
        }
        
        try {
            if (channel.isOpen()) {
                channel.close();
                log.debug("Successfully closed file channel: {}", resourceName);
            }
        } catch (IOException e) {
            log.warn("Failed to close file channel: {}", resourceName, e);
        } catch (Exception e) {
            log.error("Unexpected error closing file channel: {}", resourceName, e);
        }
    }

    /**
     * 安全关闭线程池
     * 
     * @param executorService 线程池
     * @param timeout 超时时间（秒）
     */
    public static void safeShutdownExecutor(ExecutorService executorService, int timeout) {
        if (executorService == null || executorService.isShutdown()) {
            return;
        }
        
        try {
            // 优雅关闭
            executorService.shutdown();
            if (!executorService.awaitTermination(timeout, TimeUnit.SECONDS)) {
                log.warn("Executor service did not terminate within {} seconds, forcing shutdown", timeout);
                executorService.shutdownNow();
                
                // 再次等待
                if (!executorService.awaitTermination(timeout, TimeUnit.SECONDS)) {
                    log.error("Executor service did not terminate even after force shutdown");
                }
            }
            log.debug("Successfully shutdown executor service");
        } catch (InterruptedException e) {
            log.warn("Interrupted while waiting for executor service to shutdown", e);
            Thread.currentThread().interrupt();
            executorService.shutdownNow();
        } catch (Exception e) {
            log.error("Unexpected error shutting down executor service", e);
        }
    }

    /**
     * 强制垃圾回收并等待
     * 用于确保MappedByteBuffer被释放
     * 
     * @param maxWaitTime 最大等待时间（毫秒）
     */
    public static void forceGcAndWait(long maxWaitTime) {
        try {
            // 强制垃圾回收
            System.gc();
            
            // 等待一段时间让GC完成
            long startTime = System.currentTimeMillis();
            while (System.currentTimeMillis() - startTime < maxWaitTime) {
                Thread.sleep(10);
                // 再次触发GC
                System.gc();
            }
            
            log.debug("Forced GC completed");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.warn("Interrupted during forced GC", e);
        } catch (Exception e) {
            log.warn("Error during forced GC", e);
        }
    }

    /**
     * 验证资源是否已正确释放
     * 
     * @param resource 资源对象
     * @param resourceName 资源名称
     * @return 是否已释放
     */
    public static boolean isResourceReleased(Object resource, String resourceName) {
        if (resource == null) {
            return true;
        }
        
        try {
            // 对于FileChannel，检查是否已关闭
            if (resource instanceof FileChannel) {
                FileChannel channel = (FileChannel) resource;
                boolean isClosed = !channel.isOpen();
                if (!isClosed) {
                    log.warn("FileChannel resource is still open: {}", resourceName);
                }
                return isClosed;
            }
            
            // 对于其他资源，检查是否为null
            return resource == null;
        } catch (Exception e) {
            log.warn("Error checking resource release status: {}", resourceName, e);
            return false;
        }
    }
    
    /**
     * 安全删除文件（带重试机制）
     * 
     * @param file 要删除的文件
     * @param maxRetries 最大重试次数
     * @param retryDelayMs 重试延迟（毫秒）
     * @return 是否删除成功
     */
    public static boolean safeDeleteFile(File file, int maxRetries, long retryDelayMs) {
        if (file == null || !file.exists()) {
            return true;
        }
        
        for (int i = 0; i < maxRetries; i++) {
            if (file.delete()) {
                log.debug("Successfully deleted file: {}", file.getAbsolutePath());
                return true;
            }
            
            if (i < maxRetries - 1) {
                try {
                    Thread.sleep(retryDelayMs);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
        
        log.warn("Failed to delete file after {} retries: {}", maxRetries, file.getAbsolutePath());
        return false;
    }
    
    /**
     * 安全删除文件（使用默认重试参数）
     * 
     * @param file 要删除的文件
     * @return 是否删除成功
     */
    public static boolean safeDeleteFile(File file) {
        return safeDeleteFile(file, 5, 100);
    }
    
    /**
     * 安全删除目录（递归删除所有文件和子目录）
     * 
     * @param dir 要删除的目录
     * @return 是否删除成功
     */
    public static boolean safeDeleteDirectory(File dir) {
        if (dir == null || !dir.exists()) {
            return true;
        }
        
        if (!dir.isDirectory()) {
            return safeDeleteFile(dir);
        }
        
        // 递归删除目录中的所有文件和子目录
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isFile()) {
                    if (!safeDeleteFile(file)) {
                        log.warn("Failed to delete file in directory: {}", file.getAbsolutePath());
                    }
                } else if (file.isDirectory()) {
                    if (!safeDeleteDirectory(file)) {
                        log.warn("Failed to delete subdirectory: {}", file.getAbsolutePath());
                    }
                }
            }
        }
        
        // 删除空目录
        return safeDeleteFile(dir);
    }
} 